package com.electromagnetic.industry.software.manage.service.serviceimpl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.electromagnetic.industry.software.common.enums.UserOperationModuleEnum;
import com.electromagnetic.industry.software.common.pojo.RespPageVO;
import com.electromagnetic.industry.software.common.resp.ElectromagneticResult;
import com.electromagnetic.industry.software.common.util.EleCommonUtil;
import com.electromagnetic.industry.software.common.util.ElectromagneticResultUtil;
import com.electromagnetic.industry.software.common.util.UserThreadLocal;
import com.electromagnetic.industry.software.manage.mapper.UserAccessLogMapper;
import com.electromagnetic.industry.software.manage.mapper.UserMapper;
import com.electromagnetic.industry.software.manage.pojo.models.User;
import com.electromagnetic.industry.software.manage.pojo.models.UserAccessLog;
import com.electromagnetic.industry.software.manage.pojo.req.AccessLogQueryDTO;
import com.electromagnetic.industry.software.manage.pojo.resp.AccessLogQueryVO;
import com.electromagnetic.industry.software.manage.pojo.resp.OperationModuleVO;
import com.electromagnetic.industry.software.manage.service.UserAccessLogService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class UserAccessLogServiceImpl extends ServiceImpl<UserAccessLogMapper, UserAccessLog> implements UserAccessLogService {

    @Resource
    private UserMapper userMapper;

    /**
     * 分页查询操作记录（审计）
     *
     * @param pars
     * @return
     */
    @Override
    public ElectromagneticResult<?> info(AccessLogQueryDTO pars, boolean adminQuery) {

        LambdaQueryWrapper<UserAccessLog> queryWrapper = Wrappers.lambdaQuery(UserAccessLog.class);

        if (pars.isCreatedTimeAsc()) {
            queryWrapper.orderByAsc(UserAccessLog::getCreatedTime);
        } else {
            queryWrapper.orderByDesc(UserAccessLog::getCreatedTime);
        }

        if (!adminQuery) {
            queryWrapper.orderByDesc(UserAccessLog::getCreatedTime);
            queryWrapper.eq(UserAccessLog::getDataId, pars.getDataId());
        } else {
            queryWrapper.ne(UserAccessLog::getOperationModule, UserOperationModuleEnum.TMP.key);
        }

        if (StrUtil.isNotEmpty(pars.getOperationModuleKey())) {
            queryWrapper.eq(UserAccessLog::getOperationModule, pars.getOperationModuleKey());
        }

        if (ObjUtil.isAllNotEmpty(pars.getStartCreatedTime(), pars.getEndCreatedTime())) {
            Assert.isTrue(EleCommonUtil.isWithinCertainMonths(pars.getStartCreatedTime(), pars.getEndCreatedTime(), 6), "查询时间错误");
            queryWrapper.between(UserAccessLog::getCreatedTime, pars.getStartCreatedTime(), pars.getEndCreatedTime());
        } else {
            Date minCreatedTime = DateUtil.offsetMonth(DateUtil.date(), -6);
            queryWrapper.gt(UserAccessLog::getCreatedTime, minCreatedTime);
        }

        if (StrUtil.isNotEmpty(pars.getKeyWord())) {
            Set<String> operationObjSet = new HashSet<>();
            Set<String> userIdSet = userMapper.selectList(Wrappers.<User>lambdaQuery().select(User::getId).like(User::getUserName, pars.getKeyWord())).stream().map(User::getId).collect(Collectors.toSet());
            for (UserOperationModuleEnum e : UserOperationModuleEnum.values()) {
                if (e.desc.contains(pars.getKeyWord())) {
                    operationObjSet.add(e.key);
                }
            }

            queryWrapper.and(qr -> qr.like(UserAccessLog::getAction, pars.getKeyWord())
                    .or()
                    .in(CollUtil.isNotEmpty(operationObjSet), UserAccessLog::getOperationModule, operationObjSet)
                    .or()
                    .in(CollUtil.isNotEmpty(userIdSet), UserAccessLog::getUserId, userIdSet)
                    .or()
                    .like(UserAccessLog::getRequestIp, pars.getKeyWord())
                    .or()
                    .like(UserAccessLog::getOperationMsg, pars.getKeyWord()));
        }

        Page<UserAccessLog> logs = this.baseMapper.selectPage(new Page<>(pars.getPageNum(), pars.getPageSize()), queryWrapper);
        List<UserAccessLog> records = logs.getRecords();
        List<AccessLogQueryVO> res = BeanUtil.copyToList(records, AccessLogQueryVO.class);
        setOtherInfo(res);
        UserThreadLocal.setSuccessInfo("", "", "查看操作记录成功。");
        return ElectromagneticResultUtil.success(new RespPageVO<>(logs.getTotal(), res));
    }

    @Override
    public ElectromagneticResult<?> operationModule() {

        List<OperationModuleVO> res = new ArrayList<>();
        for (UserOperationModuleEnum e : UserOperationModuleEnum.values()) {
            OperationModuleVO vo = new OperationModuleVO().setText(e.desc).setValue(e.key);
            res.add(vo);
        }
        UserThreadLocal.setSuccessInfo("", "", "查询所有操作对象成功");
        return ElectromagneticResultUtil.success(res);
    }

    private void setOtherInfo(List<AccessLogQueryVO> res) {

        List<String> userIds = res.stream().map(AccessLogQueryVO::getUserId).toList();
        if (CollUtil.isEmpty(userIds)) {
            return;
        }
        LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery(User.class).select(User::getId, User::getUserName).in(User::getId, userIds);
        Map<String, String> idNameMap = userMapper.selectList(wrapper).stream().collect(Collectors.toMap(User::getId, User::getUserName));

        res.forEach(e -> {
            e.setUserName(idNameMap.get(e.getUserId()));
            e.setOperationModule(UserOperationModuleEnum.getDesc(e.getOperationModule()));
        });

    }
}
